package jvProjects.imageDeformation;

import help.DeformationHanlderTransfare;
import deformation.Deformation;
import deformation.DeformationGenerator.DeformationType;
import deformation.point.AffinePointDeformation;
import deformation.point.RigidPointDeformation;
import deformedGrid.painter.Tile;
import deformedGrid.painter.DeformationPainter;
import fusion.LinearCombination;
import fusion.gui.FusionFrame;
import handler.DeformationLine;
import handler.DeformationPoint;
import handler.LineHandler;

import java.awt.AWTException;
import java.awt.Color;
import java.awt.FileDialog;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;

import javax.imageio.ImageIO;

import jv.anim.PsTimeEvent;
import jv.project.PjProject;
import jv.viewer.PvDisplay;
import jvDeformation.JvDeformationDisplay;
import jvDeformation.JvDeformationHandler;
import jvDeformation.JvGrid;

/**
 * @see jv.anim.PsAnimation
 * @see jv.geom.PgElementSet
 * @see jv.project.PjProject
 */
public class PjImageDeformation extends PjProject {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2417563575142658450L;

	/**
	 * Constructor, without arguments to allow loading of project from menu.
	 */
	public PjImageDeformation() {
		super("Image Deformation");

		init();
	}

	/**
	 * Do initialization of data structures; method is also used to reset
	 * instances.
	 */
	@Override
	public void init() {
		super.init();
	}
	/**
	 * Start project, e.g. start an animation. Method is called once when
	 * project is selected in PvViewer#selectProject(). Method is optional. For
	 * example, if an applet calls the start() method of PvViewer, then PvViewer
	 * tries to invoke the start() method of the currently selected project.
	 */
	
	JvDeformationDisplay defdis;
	@Override
	public void start() {

		m_display.setEnabled3DLook(false);
		Robot robo = null;
		try {
			robo = new Robot();
		} catch (AWTException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		BufferedImage bi = robo.createScreenCapture(new Rectangle(Toolkit
				.getDefaultToolkit().getScreenSize()));
		defdis = new JvDeformationDisplay(m_display, bi,
				50, 50);

		super.start();

	}

	/**
	 * Update method of project to react on changes in its panel or of its
	 * children. This method is optional, but required if project is parent of a
	 * child. Project becomes parent if child calls
	 * <code>child.setParent(this)</code> with this project as argument. For
	 * example, see the constructor of MyProject. Project must react on child
	 * events, or forward them to its superclass.
	 * <p>
	 * Catch events of integer children and recompute surface.
	 */
	@Override
	public boolean update(Object event) {
		if (event == getInfoPanel()) {

			return super.update(this);
		}
		return super.update(event);
	}

	/**
	 * Put your algorithms/methods here in the Pj...-class. They have access to
	 * the active geometry on the display and several other important objects
	 * and can be invoked from the GUI-class Pj..._IP, e.g. on button-click
	 * events. Make sure your method is public or protected so that it can be
	 * accessed by other classes.
	 */
	protected void loadImage() {
		defdis.loadnewImage();
	}

	
	public void saveImage(boolean drawHandler, boolean hq){
        FileDialog fileDialog = new FileDialog(getViewer().getFrame(), "Save", FileDialog.SAVE);
        fileDialog.setFilenameFilter(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.endsWith(".png");
            }
        });
        fileDialog.setFile("Untitled.png");
        fileDialog.setVisible(true);

        if (fileDialog.getFile() != null) {
		
			LineHandler lHandler;
			if (defdis.getJvDeformationHandler().isSticked()) {
				lHandler = defdis.getJvDeformationHandler().getLineHandler();
			}else{
				lHandler = defdis.getJvDeformationHandler().generateHandler();
			}
			
			DeformationHanlderTransfare trans = new DeformationHanlderTransfare(
					lHandler,
					defdis.getJvGrid().image.getHeight());
			LineHandler transfareLineHandler = trans.getTransfareLineHandler();
			Deformation defo = defdis.generateNewDeformation(transfareLineHandler);
			DeformationPainter dpaint;
			if (hq) {
				 dpaint = new DeformationPainter(2*defdis.gridPointsX.get(), 2*defdis.gridPointsY.get(), defdis.getJvGrid().image);
			}else{
				 dpaint = new DeformationPainter(defdis.gridPointsX.get(), defdis.gridPointsY.get(), defdis.getJvGrid().image);
					
			}
			dpaint.setDeformation(defo);
			
			
		Rectangle r = dpaint.getBounds();
		BufferedImage bi = dpaint.getImage(r);
		if (drawHandler) {
			Graphics2D g =(Graphics2D) bi.getGraphics();
			g.setColor(Color.red);
			g.translate(-r.x, -r.y);
			for (DeformationPoint p : transfareLineHandler.getMovedPoints()) {
				g.fillOval((int)p.x-10, (int)p.y-10, 20, 20);
			}
			g.setColor(Color.BLACK);
			for (DeformationLine l : transfareLineHandler.getMovedLines()) {
				g.drawLine((int)l.getStartPoint().x, (int)l.getStartPoint().y,(int) l.getEndPoint().x,(int) l.getEndPoint().y);
			}
			if (defdis.showGrid.get()) {
			for (Tile c : dpaint.getCachelList()) {
				g.draw(c.getShape());
			}
			}
			
		}

		File outputfile = new File(fileDialog.getDirectory() + fileDialog.getFile());
		try {
		ImageIO.write(bi, "png", outputfile);
	} catch (IOException e) {
		System.out.println("fail");
	}}
	}

}
